/*
       Licensed to the Apache Software Foundation (ASF) under one
       or more contributor license agreements.  See the NOTICE file
       distributed with this work for additional information
       regarding copyright ownership.  The ASF licenses this file
       to you under the Apache License, Version 2.0 (the
       "License"); you may not use this file except in compliance
       with the License.  You may obtain a copy of the License at
         http://www.apache.org/licenses/LICENSE-2.0
       Unless required by applicable law or agreed to in writing,
       software distributed under the License is distributed on an
       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
       KIND, either express or implied.  See the License for the
       specific language governing permissions and limitations
       under the License.
 */


package org.apache.cordova.geolocation;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.widget.Toast;

//import com.google.android.gms.location.LocationListener;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationRequest;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.LOG;
import org.apache.cordova.PermissionHelper;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
// 修改定位 2020年5月15日
public class Geolocation extends CordovaPlugin {

    String TAG = "GeolocationPlugin";
    CallbackContext context;

    String[] permissions = {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};


    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        Criteria criteria = new Criteria();
        criteria.setCostAllowed(false);
        Log.d(TAG, "testflag: " + testflag);
        ;

        LOG.d(TAG, "We are entering execute");
        context = callbackContext;
        if (action.equals("getPermission")) {
            if (hasPermisssion()) {
                PluginResult r = new PluginResult(PluginResult.Status.OK);
                context.sendPluginResult(r);
                return true;
            } else {
                PermissionHelper.requestPermissions(this, 0, permissions);
            }
            return true;
        } else if (action.equals("getCurrentLoaction")) {
            return getCurrentLocation();
        } else if (action.equals("getLocationOnce")) {
            getLocationOnce();
            return true;
        } else if (action.equals("startLocation")) {
            startLocation();
            return true;
        } else if (action.equals("stopLocation")) {
            stopLocation();
            return true;
        }
        return false;
    }

    LocationManager manager = null;
    String provider = null;
    String testflag = System.currentTimeMillis() + "";

    private void initLocation() {

        if (manager == null) {
            manager = (LocationManager) cordova.getActivity().getSystemService(Context.LOCATION_SERVICE);
        }
        Criteria criteria = new Criteria();
        criteria.setCostAllowed(false);//设置位置服务免费
        criteria.setAccuracy(Criteria.ACCURACY_COARSE); //设置水平位置精度
        //设置不需要获取海拔方向数据
        criteria.setAltitudeRequired(false);
        criteria.setBearingRequired(false);
        //设置允许产生资费
        criteria.setCostAllowed(true);
        //要求低耗电
        criteria.setPowerRequirement(Criteria.POWER_HIGH);
        provider = manager.getBestProvider(criteria, false);

    }

    LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            Log.d(TAG, "onLocationChanged: " + location.toString());
            JSONObject jsonObject = new JSONObject();
            try {
                jsonObject.put("latitude", location.getLatitude());
                jsonObject.put("longitude", location.getLongitude());
                jsonObject.put("altitude", location.getAltitude());
                jsonObject.put("accuracy", location.getAccuracy());
                jsonObject.put("speed", location.getSpeed());
                jsonObject.put("timestamp", location.getTime());
                JSONObject position = new JSONObject();
                position.put("coords", jsonObject);
                context.success(position);
                if (!isWatch) {
                    isStart = false;
                    manager.removeUpdates((android.location.LocationListener) locationListener);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    };
    boolean isWatch = false;//持续等位
    boolean isStart = false;

    @SuppressLint("MissingPermission")
    private void startLocation() {
        initLocation();
        isWatch = true;
        manager.requestLocationUpdates(provider, 1000, 1, locationListener);
        this.isStart = true;
        context.success();
    }

    @SuppressLint("MissingPermission")
    private void getLocationOnce() {

        initLocation();
        isStart = true;
        manager.requestLocationUpdates(provider, 1000, 1, locationListener);
    }

    private void stopLocation() {
        if (manager != null)
            manager.removeUpdates(locationListener);
    }

    private boolean getCurrentLocation() throws JSONException {
        initLocation();
        Log.i(TAG, "we choose " + provider);
        if (provider != null) {
            if (ActivityCompat.checkSelfPermission(cordova.getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(cordova.getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                context.error("没有权限");
                return false;
            }
            if (!isOPen()) {
                Toast.makeText(cordova.getActivity().getApplicationContext(), "请先打开定位", Toast.LENGTH_LONG).show();
                context.error("请先打开定位");
                return false;
            }
            Location location = manager.getLastKnownLocation(provider);
            if (location == null) {
                List<String> hasUsed = new ArrayList<>();
                hasUsed.add(provider);
                List<String> allProviders = manager.getAllProviders();
                for (int i=0;i<allProviders.size();i++){
                    if(hasUsed.contains(allProviders.get(i))){
                        continue;
                    }
                    location = manager.getLastKnownLocation(allProviders.get(i));
                    if(location==null){
                        hasUsed.add(allProviders.get(i));
                        continue;
                    }
                    Log.e(TAG, "getCurrentLocation: "+allProviders.get(i) );
                    break;
                }
                if(location==null){
                    context.error("定位失败,请尝试移动位置");
                    return false;
                }
            }
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("latitude", location.getLatitude());
            jsonObject.put("longitude", location.getLongitude());
            jsonObject.put("altitude", location.getAltitude());
            jsonObject.put("accuracy", location.getAccuracy());
            jsonObject.put("speed", location.getSpeed());
            jsonObject.put("timestamp", location.getTime());
            JSONObject position = new JSONObject();
            position.put("coords", jsonObject);
            context.success(position);
            return true;
        } else {
//            Toast.makeText(cordova.getActivity(), "1.请检查网络连接 \n2.请打开我的位置", Toast.LENGTH_SHORT).show();
            context.error("1.请检查网络连接 \n2.请打开我的位置");
            return false;
        }
    }

    /**
     * 判断GPS是否开启，GPS或者AGPS开启一个就认为是开启的
     *
     * @return true 表示开启
     */
    public final boolean isOPen() {
        // 通过GPS卫星定位，定位级别可以精确到街（通过24颗卫星定位，在室外和空旷的地方定位准确、速度快）
        boolean gps = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        // 通过WLAN或移动网络(3G/2G)确定的位置（也称作AGPS，辅助GPS定位。主要用于在室内或遮盖物（建筑群或茂密的深林等）密集的地方定位）
        boolean network = manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        if (gps || network) {
            return true;
        }

        return false;
    }

    private boolean getUpdateLocation() throws JSONException {
        initLocation();
        Log.i(TAG, "we choose " + provider);
        if (provider != null) {
            if (ActivityCompat.checkSelfPermission(cordova.getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(cordova.getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                context.error("没有权限");
                return false;
            }
            Location location = manager.getLastKnownLocation(provider);
            //第一次获得设备的位置
//        updateLocation(location);
            //重要函数，监听数据测试
//        manager.requestLocationUpdates(provider, 6000, 10,
//                locationListener);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("latitude", location.getLatitude());
            jsonObject.put("longitude", location.getLongitude());
            jsonObject.put("altitude", location.getAltitude());
            jsonObject.put("accuracy", location.getAccuracy());
            jsonObject.put("speed", location.getSpeed());
            jsonObject.put("timestamp", location.getTime());
            JSONObject position = new JSONObject();
            position.put("coords", jsonObject);
            context.success(position);
            return true;
        } else {
//            Toast.makeText(cordova.getActivity(), "1.请检查网络连接 \n2.请打开我的位置", Toast.LENGTH_SHORT).show();
            context.error("1.请检查网络连接 \n2.请打开我的位置");
            return false;
        }
    }

    public void onRequestPermissionResult(int requestCode, String[] permissions,
                                          int[] grantResults) throws JSONException {
        PluginResult result;
        //This is important if we're using Cordova without using Cordova, but we have the geolocation plugin installed
        if (context != null) {
            for (int r : grantResults) {
                if (r == PackageManager.PERMISSION_DENIED) {
                    LOG.d(TAG, "Permission Denied!");
                    result = new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION);
                    context.sendPluginResult(result);
                    return;
                }

            }
            result = new PluginResult(PluginResult.Status.OK);
            context.sendPluginResult(result);
        }
    }

    public boolean hasPermisssion() {
        for (String p : permissions) {
            if (!PermissionHelper.hasPermission(this, p)) {
                return false;
            }
        }
        return true;
    }

    /*
     * We override this so that we can access the permissions variable, which no longer exists in
     * the parent class, since we can't initialize it reliably in the constructor!
     */

    public void requestPermissions(int requestCode) {
        PermissionHelper.requestPermissions(this, requestCode, permissions);
    }


}
